package com.kunkun.auth.domain.service.Impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.gson.Gson;
import com.kunkun.auth.common.entity.PageResult;
import com.kunkun.auth.common.enums.AuthUserStatusEnum;
import com.kunkun.auth.common.enums.IsDeletedFlagEnum;
import com.kunkun.auth.domain.bo.AuthUserBO;
import com.kunkun.auth.domain.constants.AuthConstant;
import com.kunkun.auth.domain.convert.AuthUserBOConverter;
import com.kunkun.auth.domain.redis.RedisUtil;
import com.kunkun.auth.domain.service.AuthUserDomainService;
import com.kunkun.auth.infra.basic.entity.*;
import com.kunkun.auth.infra.basic.service.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {

    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;

    @Resource
    private AuthPermissionService authPermissionService;


    private String salt = "chicken";

    @Resource
    private RedisUtil redisUtil;

    private String authPermissionPrefix = "auth.permission";

    private String authRolePrefix = "auth.role";

    private static final String LOGIN_PREFIX = "loginCode";




    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        //校验用户是否存在
        AuthUser existAuthUser = new AuthUser();
        if(authUserBO.getUserName() == null || authUserBO.getUserName().trim().equals("")){
            existAuthUser.setPhone(authUserBO.getPhone());
        }else {
            existAuthUser.setUserName(authUserBO.getUserName());
        }
        List<AuthUser> existUser = authUserService.queryByCondition(existAuthUser);
        if (existUser.size() > 0) {
            return true;
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        if (StringUtils.isNotBlank(authUser.getPassword())) {
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), salt));
        }
        if (StringUtils.isBlank(authUser.getAvatar())) {
            authUser.setAvatar("http://175.178.35.85:9000/kunkun/icon/kunkun.jpg");
        }
        if (StringUtils.isBlank(authUser.getNickName())) {
            authUser.setNickName("kunkun粉丝");
        }

        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        Integer count = authUserService.insert(authUser);

        //建立一个初步的角色的关联
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole roleResult = authRoleService.queryByCondition(authRole);
        Long roleId = roleResult.getId();
        Long userId = authUser.getId();
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(userId);
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);

        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        redisUtil.set(roleKey, new Gson().toJson(roleList));
        //根据roleId查权限id列表
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> rolePermissionList = authRolePermissionService.
                queryByCondition(authRolePermission);
        //获取权限Id
        List<Long> permissionIdList = rolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId).collect(Collectors.toList());
        //根据permissionId查权限
        List<AuthPermission> permissionList = authPermissionService.queryByRoleList(permissionIdList);
        String permissionKey = redisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        redisUtil.set(permissionKey, new Gson().toJson(permissionList));

        return count > 0;
    }

    @Override
    public Boolean update(AuthUserBO authUserBO) {

        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
//        if (authUserBO.getStatus() == null || authUserBO.getStatus() == AuthUserStatusEnum.OPEN.getCode()) {
//            authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
//        }
        if (StringUtils.isNotBlank(authUserBO.getPassword())) {
            authUser.setPassword(SaSecureUtil.md5BySalt(authUserBO.getPassword(), salt));
        }
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        Integer count = authUserService.update(authUser);
        //有任何的更新，都要与缓存进行同步的修改要把当前用户的角色和权限都刷到我们的redis里
        return count > 0;
    }

    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        //有任何的更新，都要与缓存进行同步的修改要把当前用户的角色和权限都刷到我们的redis里
        int count = authUserService.update(authUser);
        return count > 0;
    }

    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {

        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> userList = authUserService.queryByCondition(authUser);
        if (CollectionUtils.isEmpty(userList)) {
            return new AuthUserBO();
        }
        AuthUser user = userList.get(0);
        return AuthUserBOConverter.INSTANCE.convertEntityToBO(user);
    }

    @Override
    public List<AuthUserBO> listUserInfoByIds(List<String> ids) {
        return null;
    }

    @Override
    public SaTokenInfo doLogin(String validCode) {
        String loginKey = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(loginKey);
        if (StringUtils.isBlank(openId)) {
            return null;
        }
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(openId);
        this.register(authUserBO);
        StpUtil.login(openId);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return tokenInfo;
    }

    @Override
    public SaTokenInfo doLoginByPassword(String username, String password) {

        AuthUserBO authUserBO = new AuthUserBO();
        if(username.matches("^[-+]?\\d+(\\.\\d+)?$")){
            authUserBO.setPhone(username);
        }else {
            authUserBO.setUserName(username);
        }
        authUserBO.setPassword(password);

        AuthUser existAuthUser = new AuthUser();
        if (StringUtils.isNotBlank(authUserBO.getPassword())) {
            existAuthUser.setPassword(SaSecureUtil.md5BySalt(authUserBO.getPassword(), salt));
        }
        if(authUserBO.getUserName() == null || authUserBO.getUserName().trim().equals("")){
            existAuthUser.setPhone(authUserBO.getPhone());
        }else {
            existAuthUser.setUserName(authUserBO.getUserName());
        }
        List<AuthUser> existUser = authUserService.queryByCondition(existAuthUser);
        if(existUser!=null && !existUser.isEmpty()){
            username = existUser.get(0).getUserName();
            StpUtil.login(username, password);
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return tokenInfo;
        }


        return null;
    }

    @Override
    public PageResult<AuthUserBO> getUserList(AuthUserBO authUserBO) {

        PageResult<AuthUserBO> pageResult = new PageResult<>();
        pageResult.setPageNo(authUserBO.getPageNo());
        pageResult.setPageSize(authUserBO.getPageSize());
        int start = (authUserBO.getPageNo() - 1) * authUserBO.getPageSize();
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        int count = authUserService.countByCondition();
        if (count == 0) {
            return pageResult;
        }

        List<AuthUser> userList = authUserService.queryPage(authUser,start,authUserBO.getPageSize());
        List<AuthUserBO> userBOS = AuthUserBOConverter.INSTANCE.convertEntityListToBO(userList);

        pageResult.setRecords(userBOS);
        pageResult.setTotal(count);
        return pageResult;
    }

    @Override
    public boolean updatePassword(Integer id, String oldPassword, String newPassword) {

        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setId(Long.valueOf(id));
        authUserBO.setPassword(oldPassword);
        if (StringUtils.isNotBlank(authUserBO.getPassword())) {
            authUserBO.setPassword(SaSecureUtil.md5BySalt(authUserBO.getPassword(), salt));
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        List<AuthUser> userList = authUserService.queryByCondition(authUser);

        if (StringUtils.isNotBlank(userList.get(0).getUserName())) {
            authUser.setPassword(SaSecureUtil.md5BySalt(newPassword, salt));
        }
        int count = authUserService.update(authUser);

        return count > 0;
    }


}
